package util;

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
import java.util.LinkedList;

import javax.lang.model.element.Element;

public class BlockingQueueTB<T> {

	private LinkedList<T> elements;
	private boolean isclosed = false;
	
	@Target ({ElementType.TYPE,ElementType.METHOD})
	public @interface Producer {}
	
	@Target ({ElementType.TYPE,ElementType.METHOD})
	public @interface Consummer {}

	
	public  BlockingQueueTB() {
		elements = new LinkedList<T>();

	}
	
	synchronized public void enqueue(T element) {

		if (isclosed) {
			throw new ClosedException();
		} else {
			elements.add(element);
			notifyAll();
			
			
		}
		
	}

	synchronized public T dequeue() {

		while (elements.isEmpty()) {
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();  
			}
		}

		if (isclosed) {
			throw new ClosedException();
		} else {
			return elements.pollFirst();
			
		}

	}
	
	synchronized public T dequeueLast() {

		while (elements.isEmpty()) {
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		if (isclosed) {
			throw new ClosedException();
		} else {
			return elements.pollLast();
			
		}

	}

	synchronized public T getAt(int position) {

		while (elements.isEmpty()) {
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		if (isclosed) {
			throw new ClosedException();
		} else {
			return elements.get(position);
			
		}

	}
	
	synchronized public void close() {
		isclosed = true;
	}
	
	public int GetSize(){
		return elements.size();
	}

}
